﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace KATS_Client.UI
{
    /// <summary>
    /// The main window of the program
    /// </summary>
    public partial class MainWindow : Form
    {
        /// <summary>
        /// The main window
        /// </summary>
        public static MainWindow mainWindow;

        /// <summary>
        /// Create the window
        /// </summary>
        public MainWindow()
        {
            mainWindow = this;
            int rv = ProgressReporting.Start("Creating window");
            InitializeComponent();
            Generate();

            Client.FileActionsQueue.QueueChanged += new EventHandler<EventArgs>(FileActionsQueue_QueueChanged);
            Client.FileActionsQueue.QueueLoaded += new EventHandler<EventArgs>(FileActionsQueue_QueueLoaded);
            Update_QueueLengthText();

            Client.FileActionsQueue.Active_Changed += new EventHandler<EventArgs>(FileActionsQueue_Active_Changed);
            Update_ProcessingActiveText();

            Client.ServerConnection.ServerStatus_Changed += new EventHandler<EventArgs>(FileActionsQueue_ServerStatus_Changed);
            Update_ServerStatusChanged();


            Client.FileActionsQueue.FileActionUpdate += new EventHandler<KATS_Client.Client.FileActionProgress>(FileActionsQueue_FileActionUpdate);
            Client.FileActionsQueue.FileActionCompleted += new EventHandler<KATS_Client.Client.FileActionProgress>(FileActionsQueue_FileActionCompleted);

            Server.Server.ProgressUpdate += new EventHandler<KATS_Client.Client.FileActionProgress>(Server_ProgressUpdate);

            WindowManager.WindowSetChanged += new EventHandler<EventArgs>(WindowManager_WindowSetChanged);

            Program.Exiting += new EventHandler<EventArgs>(Program_Exiting);

            ProgressReporting.End(rv, "Created window");
        }


        /// <summary>
        /// The program is closing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Program_Exiting(object sender, EventArgs e)
        {
            if (this.NotifyIcon1 != null)
            {
                this.NotifyIcon1.Container.Remove(this.NotifyIcon1);
                this.NotifyIcon1.Dispose();
            }
        }


        /// <summary>
        /// The window set has changed. Redraw the windows
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void WindowManager_WindowSetChanged(object sender, EventArgs e)
        {
            Generator.AttachWindows();
        }

        /// <summary>
        /// The current file action has completed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FileActionsQueue_FileActionCompleted(object sender, KATS_Client.Client.FileActionProgress e)
        {
            Update_ProgressBar(0, string.Empty);
        }

        /// <summary>
        /// The current file action has progressed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FileActionsQueue_FileActionUpdate(object sender, KATS_Client.Client.FileActionProgress e)
        {
            Update_ProgressBar(e.PercentageComplete, e.Speed);
        }

        /// <summary>
        /// The server has updated its progress
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Server_ProgressUpdate(object sender, Client.FileActionProgress e)
        {
            string speed = e.Speed;
            
            int? percent = null;
            if (e.PercentageComplete >= 0 && e.PercentageComplete <= 100)
                percent = e.PercentageComplete;
            Update_ProgressBar(percent, speed);
        }


        /// <summary>
        /// Update the progress bar speed
        /// </summary>
        /// <param name="PercentageComplete">The percentage that is completed</param>
        /// <param name="Speed">The speed/tooltip text</param>
        void Update_ProgressBar(int? PercentageComplete, string Speed)
        {
            if (this.InvokeRequired)
            {
                // invoke this
                Delegate_UpdateProgressBar b = new Delegate_UpdateProgressBar(Update_ProgressBar2);
                object[] parms = new object[2];
                parms[0] = PercentageComplete;
                parms[1] = Speed;
                this.Invoke(b,parms);
            }
            else
            {
                // dont invoke, just process
                Update_ProgressBar2(PercentageComplete, Speed);
            }
        }
        /// <summary>
        /// The delegate used to safely update the progress bar
        /// </summary>
        delegate void Delegate_UpdateProgressBar(int? percentage, string speed);

        /// <summary>
        /// Update the progress bar speed
        /// </summary>
        /// <param name="PercentageComplete">The percentage that is completed</param>
        /// <param name="Speed">The speed/tooltip text</param>
        void Update_ProgressBar2(int? PercentageComplete, string Speed)
        {
            if (PercentageComplete.HasValue)
                this.TransferProgress.Value = PercentageComplete.Value;
            if(Speed != null)
                this.TransferProgress.ToolTipText = Speed;
        }

        /// <summary>
        /// The server status has changed, so update the UI
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FileActionsQueue_ServerStatus_Changed(object sender, EventArgs e)
        {
            Update_ServerStatusChanged();
        }

        /// <summary>
        /// Update the server status text
        /// </summary>
        public void Update_ServerStatusChanged()
        {
            Update_ServerStatusChanged(Client.ServerConnection.ServerStatus);
        }

        /// <summary>
        /// Update the server status text
        /// </summary>
        /// <param name="status">The status</param>
        void Update_ServerStatusChanged(bool status)
        {
            string msg = null;
            Image img = null;

            if (status)
            {
                msg = "Server Online";
                img = Properties.Resources.ServerStatus_online;
                this.ServerStatus.Text = msg;
                this.ServerStatus.ToolTipText = msg;
                this.ServerStatus.Image = img;

                // refresh all remote tab data
                WindowManager.Refresh_AllTabs_Threaded(true);
            }
            else
            {
                if (!Client.ServerConnection.Authenticated)
                {
                    msg = "Authentication failed";
                }
                else
                {
                    msg = "Server Offline";
                }
                img = Properties.Resources.ServerStatus_offline;
                this.ServerStatus.Text = msg;
                this.ServerStatus.ToolTipText = msg;
                this.ServerStatus.Image = img;
            }
        }

        /// <summary>
        /// The processing status has changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FileActionsQueue_Active_Changed(object sender, EventArgs e)
        {
            Update_ProcessingActiveText();
        }

        /// <summary>
        /// Updates the processing active text object
        /// </summary>
        public void Update_ProcessingActiveText()
        {
            Update_ProcessingActiveText(Client.FileActionsQueue.Active);
        }

        /// <summary>
        /// Update the processing active text object
        /// </summary>
        /// <param name="active">The active status</param>
        void Update_ProcessingActiveText(bool active)
        {
            string msg = null;
            Image img = null;
            if (active)
            {
                msg = "Processing Active";
                img = Properties.Resources.ServerStatus_online;
            }
            else
            {
                msg = "Processing Disabled";
                img = Properties.Resources.ServerStatus_offline;
            }
            this.ProcessingActive.Image = img;
            this.ProcessingActive.Text = msg;
        }

        /// <summary>
        /// The queue has been loaded
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FileActionsQueue_QueueLoaded(object sender, EventArgs e)
        {
            Update_QueueLengthText();
        }

        /// <summary>
        /// The queue has changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FileActionsQueue_QueueChanged(object sender, EventArgs e)
        {
            Update_QueueLengthText();
        }

        /// <summary>
        /// Develope the UI
        /// </summary>
        public void Generate()
        {
            Generator.Generate(this);
        }


        /// <summary>
        /// Update the queu length text displayed
        /// </summary>
        public void Update_QueueLengthText()
        {
            UpdateQueueLengthText(Client.FileActionsQueue.QueuedActions.Count);
        }

        /// <summary>
        /// Set the queue length message to the correct value
        /// </summary>
        /// <param name="size"></param>
        void UpdateQueueLengthText(int size)
        {
            string msg = string.Format("Queue Size: {0}", size);
            this.NumberOfItemsInQueue.Text = msg;
        }

        /// <summary>
        /// Add a local window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void localToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WindowManager.Add_EmptyWindow(true);
        }

        /// <summary>
        /// Add a remote window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void remoteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WindowManager.Add_EmptyWindow(false);
        }

        /// <summary>
        /// Hovering over the remove remote window button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RemoveWindowToolStripMenuItem_MouseEnter(object sender, EventArgs e)
        {
            // add all the items to this menu item

            ToolStripDropDownItem master = (ToolStripDropDownItem)sender;
            // empty the list
            master.DropDownItems.Clear();

            int numberOfWindows = WindowManager.Windows.Count;
            for (int i = 1; i <= numberOfWindows; i++)
            {
                ToolStripMenuItem mi = new ToolStripMenuItem();
                string msg = string.Format("Window {0}", i);
                mi.Text = msg;
                mi.ToolTipText = string.Format("Remove {0}",msg);
                mi.Tag = WindowManager.Windows[i - 1];
                mi.Click += new EventHandler(RemoveWindowItem_Click);
                master.DropDownItems.Add(mi);
            }
        }

        /// <summary>
        /// Remove a particular window from the system
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void RemoveWindowItem_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem clicker = (ToolStripMenuItem)sender;
            Window window = (Window)clicker.Tag;

            // remove the window
            WindowManager.Remove_Window(window);
        }

        /// <summary>
        /// The exit button for the program has been clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Program.Exit();
        }

        /// <summary>
        /// The processing active text has been clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProcessingActive_Click(object sender, EventArgs e)
        {
            Client.FileActionsQueue.Active = !Client.FileActionsQueue.Active;
        }

        /// <summary>
        /// Icon double clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void NotifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            Toggle_Window_Visible();
        }

        /// <summary>
        /// Toggle the visible status of the window
        /// </summary>
        public void Toggle_Window_Visible()
        {
            if (this.Visible)
                HideWindow();
            else
                ShowWindow();
        }

        /// <summary>
        /// The old state
        /// </summary>
        FormWindowState oldState;

        /// <summary>
        /// The old state
        /// </summary>
        FormWindowState OldState
        {
            get
            {
                return oldState;
            }
            set { this.oldState = value; }
        }


        /// <summary>
        /// Show the window
        /// </summary>
        public void ShowWindow()
        {
            if (!this.Visible)
            {
                this.Visible = true;
                if (this.OldState == FormWindowState.Minimized)
                    this.WindowState = FormWindowState.Normal;
                else
                    this.WindowState = this.OldState;
            }
        }

        /// <summary>
        /// Hide the window
        /// </summary>
        public void HideWindow()
        {
            if (this.Visible)
            {
                this.OldState = this.WindowState;
                this.Visible = false;
            }
        }

        /// <summary>
        /// Hide/show button in notify icon context menu clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void hideShowToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Toggle_Window_Visible();
        }

        /// <summary>
        /// The user has selected for the form to close
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            HideWindow();
        }

        /// <summary>
        /// The window has been resized
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainWindow_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.HideWindow();
            }
        }

        /// <summary>
        /// Exit button in nofity icon context menu clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void exitToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Program.Exit();
        }

        /// <summary>
        /// Toggle status button in menu strip clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toggleStatusToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Client.FileActionsQueue.Active = !Client.FileActionsQueue.Active;
        }

        /// <summary>
        /// Clear queue button in menu strip clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void clearQueueToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Client.FileActionsQueue.Clear();
        }

        /// <summary>
        /// View queue button has been clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void viewToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            DisplayQueue();
        }

        
        /// <summary>
        /// Display the queue to the users
        /// </summary>
        void DisplayQueue()
        {
            if (Client.FileActionsQueue.Count != 0)
            {
                // display the queue
                QueueView queueView = new QueueView();
                queueView.ShowDialog();
            }
        }

        /// <summary>
        /// Display the authentication details dialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void authenicationDetailsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AuthenticationDetails d = new AuthenticationDetails();
            d.Show();
        }

        /// <summary>The about button in the menu system have been selected</summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutKATS about = new AboutKATS();
            about.Show();
        }

        /// <summary>Refresh all tabs</summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void allToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WindowManager.Refresh_AllTabs_Threaded();
        }

        /// <summary>Refresh all remote tabs</summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void remoteToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            WindowManager.Refresh_AllTabs_Threaded(true);
        }

        /// <summary>Refresh all local tabs</summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void localToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            WindowManager.Refresh_AllTabs_Threaded(false);
        }

        /// <summary>Refresh only the current tabs</summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void currentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WindowManager.Refresh_CurrentTabs_Threaded();
        }

        /// <summary>
        /// Resets all file extension images in the system
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Tab.RemoveFileExtensionImages();
            WindowManager.Refresh_AllTabs_Threaded();
        }



    }
}
